﻿/***********************************************
*	工作室 : 天光工作室
*	作者   : 张东斌	
*	用途   : 
*************************************************/
#include "stdafx.h"
#include "mendc.h"

void WINAPI AlphaBlend( HDC hdcResult, int nX, int nY, int nWidth, int nHeight, HDC hdcDest, int nXDest, int nYDest, HDC hdcSrc, int nXSrc, int nYSrc, BYTE bAlpha )
{
	BITMAPINFOHEADER bih;

	bih.biSize			= sizeof( BITMAPINFOHEADER );
	bih.biWidth			= nWidth;
	bih.biHeight		= nHeight;
	bih.biPlanes		= 1;
	bih.biBitCount		= 32;
	bih.biCompression	= BI_RGB;
	bih.biSizeImage		= 0;
	bih.biXPelsPerMeter	= 0;
	bih.biYPelsPerMeter	= 0;
	bih.biClrUsed		= 0;
	bih.biClrImportant	= 0;

	DWORD	*pdwSrc, *pdwDest;
	HBITMAP	hbmpSrc, hbmpDest;

	hbmpSrc  = ::CreateDIBSection( hdcSrc, (BITMAPINFO*)&bih, DIB_RGB_COLORS, (void**)&pdwSrc, 0, (DWORD)0 );
	hbmpDest = ::CreateDIBSection( hdcDest,(BITMAPINFO*)&bih, DIB_RGB_COLORS, (void**)&pdwDest,0, (DWORD)0 );

	HDC		hdcMem  = ::CreateCompatibleDC( NULL );
	HGDIOBJ hobjOld = ::SelectObject( hdcMem, hbmpDest );
	::BitBlt( hdcMem, 0, 0, nWidth, nHeight, hdcDest, nXDest, nYDest, SRCCOPY );
	::SelectObject( hdcMem, hbmpSrc );
	::BitBlt( hdcMem, 0, 0, nWidth, nHeight, hdcSrc,  nXSrc,  nYSrc,  SRCCOPY );

	for( int i=0; i<nHeight; ++i )
	{
		LPBYTE pbRGBSrc  = (LPBYTE)&pdwSrc [i*nWidth];
		LPBYTE pbRGBDest = (LPBYTE)&pdwDest[i*nWidth];

		for ( int j=0; j<nWidth; ++j )
		{
			pbRGBSrc[0] = (BYTE)(( pbRGBDest[0]*(255-bAlpha)+pbRGBSrc[0]*bAlpha )>>8);
			pbRGBSrc[1] = (BYTE)(( pbRGBDest[1]*(255-bAlpha)+pbRGBSrc[1]*bAlpha )>>8);
			pbRGBSrc[2] = (BYTE)(( pbRGBDest[2]*(255-bAlpha)+pbRGBSrc[2]*bAlpha )>>8);

			pbRGBSrc  += 4;
			pbRGBDest += 4;
		}
	}

	::BitBlt( hdcResult, nX, nY, nWidth, nHeight, hdcMem, 0, 0, SRCCOPY );
	::SelectObject( hdcMem, hobjOld );
	::DeleteDC( hdcMem );
	::DeleteObject( hbmpSrc );
	::DeleteObject( hbmpDest );
}

void WINAPI DrawAnimation( RECT *prect, HDC hDCDest, HDC hDCSrc, int nType, int nStep, int nTimeDelay )
{
	ASSERT( nStep >= 0 );
	ASSERT( nTimeDelay >= 0 );

	const int nLeft   = prect->left;
	const int nTop    = prect->top;
	const int nRight  = prect->right;
	const int nBottom = prect->bottom;
	const int nWidth  = nRight  - nLeft;
	const int nHeight = nBottom - nTop;

	if ( nStep )//&& nWidth>1 && nHeight>1 )
		switch ( nType)
	{
		case ANIMATE_NONE:
			break;

		case ANIMATE_SLIDE_TTB:
			{
				while( nHeight/nStep == 0 )
					--nStep;

				int nStepHeight = nHeight / nStep;
				for ( int ntmpHeight=nStepHeight; ntmpHeight<nHeight; ntmpHeight+=nStepHeight )
				{
					::BitBlt( hDCDest, nLeft, nTop, nWidth, ntmpHeight, hDCSrc, 0, nHeight-ntmpHeight, SRCCOPY );
					Sleep( nTimeDelay / nStep );
				}
			}	break;

		case ANIMATE_SLIDE_LTR:
			{
				while( nWidth/nStep == 0 )
					--nStep;

				int nStepWidth = nWidth / nStep;
				for ( int ntmpWidth=nStepWidth; ntmpWidth<nWidth; ntmpWidth+=nStepWidth )
				{
					::BitBlt( hDCDest, nLeft, nTop, ntmpWidth, nHeight, hDCSrc, nWidth-ntmpWidth, 0, SRCCOPY );
					Sleep( nTimeDelay / nStep );
				}
			}	break;

		case ANIMATE_UNFOLD_MTTB:
			{
				while( nHeight/nStep == 0 )
					--nStep;

				int nMiddleCY	= nHeight / 2;
				int nStepHeight = nHeight / nStep;
				int ntmpHeight  = nStepHeight;
				for( ; ntmpHeight<nHeight; ntmpHeight+=nStepHeight )
				{
					::BitBlt( hDCDest, nLeft, nTop+nMiddleCY-ntmpHeight/2, nWidth, ntmpHeight, hDCSrc, 0, nMiddleCY-ntmpHeight/2, SRCCOPY );
					Sleep( nTimeDelay / nStep );
				}
			}	break;

		case ANIMATE_UNFOLD_MTLR:
			{
				while( nWidth/nStep == 0 )
					--nStep;

				int nMiddleCX  = nWidth / 2;
				int nStepWidth = nWidth / nStep;
				int ntmpWidth  = nStepWidth;
				for( ; ntmpWidth<nWidth; ntmpWidth+=nStepWidth )
				{
					::BitBlt( hDCDest, nLeft+nMiddleCX-ntmpWidth/2, nTop, ntmpWidth, nHeight, hDCSrc, nMiddleCX-ntmpWidth/2, 0, SRCCOPY );
					Sleep( nTimeDelay / nStep );
				}
			}	break;

		case ANIMATE_SHUTTER_TTB:
			{
				while( nHeight/nStep/nStep == 0 )
					--nStep;

				int nStepHeight   = nHeight / nStep / nStep;
				int nTotalShutter = nHeight / nStep;
				int nShutterHeight= nHeight / nStep;
				int ntmpHeight	  = nStepHeight;

				for( ; ntmpHeight<nShutterHeight; ntmpHeight+=nStepHeight )
				{
					for( int i=0; i<nTotalShutter; i++ )
						::BitBlt( hDCDest, nLeft, nTop+nShutterHeight*i, nWidth, ntmpHeight, hDCSrc, 0, nShutterHeight*i, SRCCOPY );
					Sleep( nTimeDelay / nStep );
				}
			}	break;

		case ANIMATE_SHUTTER_LTR:
			{
				while( nWidth/nStep/nStep == 0 )
					--nStep;

				int nStepWidth    = nWidth / nStep / nStep;
				int nTotalShutter = nWidth / nStep;
				int nShutterWidth = nWidth / nStep;
				int ntmpWidth	  = nStepWidth;

				for( ; ntmpWidth<nShutterWidth; ntmpWidth+=nStepWidth )
				{
					for( int i=0; i<nTotalShutter; i++ )
						::BitBlt( hDCDest, nLeft+nShutterWidth*i, nTop, ntmpWidth, nHeight, hDCSrc, nShutterWidth*i, 0, SRCCOPY );
					Sleep( nTimeDelay / nStep );
				}
			}	break;

		case ANIMATE_UNFOLD_LTTRB:
			{
				for ( int i=0; i<nStep; ++i)
				{
					int ntmpWidth   = nTop  + nWidth  * (i + 1) / nStep;
					int ntmpHeight  = nLeft + nHeight * (i + 1) / nStep;
					::BitBlt( hDCDest, nLeft, nTop, ntmpWidth, ntmpHeight, hDCSrc, 0, 0, SRCCOPY);
					Sleep( nTimeDelay / nStep );
				}
			}	break;

		case ANIMATE_UNFOLDSLIDE_LTTRB:
			{
				while( nWidth/nStep == 0 || nHeight/nStep == 0 )
					--nStep;

				int nStepWidth  = nWidth / nStep;
				int nStepHeight = nHeight / nStep;
				int ntmpWidth   = nStepWidth;
				int ntmpHeight  = nStepHeight;

				for ( ; ntmpHeight<nHeight; ntmpWidth+=nStepWidth, ntmpHeight+=nStepHeight )
				{
					::BitBlt( hDCDest, nLeft, nTop, ntmpWidth, ntmpHeight, hDCSrc, 0, nHeight-ntmpHeight, SRCCOPY );
					Sleep( nTimeDelay / nStep );
				}
			}	break;

		case ANIMATE_STRETCH_TTB:
			{
				while( nHeight/nStep == 0 )
					--nStep;

				int nStepHeight = nHeight / nStep;
				for ( int ntmpHeight = nStepHeight; ntmpHeight<nHeight; ntmpHeight+=nStepHeight )
				{
					::StretchBlt( hDCDest, nLeft, nTop, nWidth, ntmpHeight, hDCSrc, 0, 0, nWidth, nHeight, SRCCOPY );
					Sleep( nTimeDelay / nStep );
				}
			}	break;	

		case ANIMATE_STRETCH_LTR:
			{
				while( nWidth/nStep == 0 )
					--nStep;

				int nStepWidth = nWidth / nStep;
				for ( int ntmpWidth = nStepWidth; ntmpWidth<nWidth; ntmpWidth+=nStepWidth )
				{
					::StretchBlt( hDCDest, nLeft, nTop, ntmpWidth, nHeight, hDCSrc, 0, 0, nWidth, nHeight, SRCCOPY );
					Sleep( nTimeDelay / nStep );
				}
			}	break;	

		case ANIMATE_NOISE:
			{
				int nCount = nWidth * nHeight / 2;
				for (int i = 0; i < nCount; ++i)
				{
					int nX = nLeft + rand() % nWidth;
					int nY = nTop  + rand() % nHeight;
					::SetPixel( hDCDest, nX, nY, ::GetPixel( hDCSrc, nX, nY ) );
					//				Sleep( nTimeDelay / nStep );
				}
			}	break;

		case ANIMATE_FADE:
			{
				HDC hdcBkgnd = ::CreateCompatibleDC( hDCDest );
				HBITMAP	hbmpBkgnd = ::CreateCompatibleBitmap( hDCDest, nWidth, nHeight );
				HGDIOBJ hobjOldB  = ::SelectObject( hdcBkgnd, hbmpBkgnd );
				::BitBlt( hdcBkgnd, 0, 0, nWidth, nHeight, hDCDest, nLeft, nTop, SRCCOPY );

				HDC hdcFade = ::CreateCompatibleDC( hDCDest );
				HBITMAP	hbmpFade = ::CreateCompatibleBitmap( hDCDest, nWidth, nHeight );
				HGDIOBJ hobjOldF = ::SelectObject( hdcFade, hbmpFade );

				for ( int i=0; i<nStep; ++i )
				{
					AlphaBlend( hdcFade, 0, 0, nWidth, nHeight, hdcBkgnd, 0, 0, hDCSrc, 0, 0, (255*i)/nStep );
					::BitBlt( hDCDest, nLeft, nTop, nWidth, nHeight, hdcFade, 0, 0, SRCCOPY );
					Sleep( nTimeDelay / nStep / 3 );
				}

				::SelectObject( hdcBkgnd, hobjOldB );
				::DeleteObject( hbmpBkgnd );
				::DeleteDC( hdcBkgnd );

				::SelectObject( hdcFade, hobjOldF );
				::DeleteObject( hbmpFade );
				::DeleteDC( hdcFade );
			}	break;

		case ANIMATE_RAND:
			{
				UINT uAnimateType[13] = { ANIMATE_SLIDE_TTB,	ANIMATE_SLIDE_LTR,
					ANIMATE_UNFOLD_MTTB,	ANIMATE_UNFOLD_MTLR,		
					ANIMATE_SHUTTER_TTB,	ANIMATE_SHUTTER_LTR,
					ANIMATE_STRETCH_TTB,	ANIMATE_STRETCH_LTR,
					ANIMATE_UNFOLD_LTTRB,	ANIMATE_UNFOLDSLIDE_LTTRB, 
					ANIMATE_NOISE,			
					ANIMATE_FADE,
					ANIMATE_NONE };

				DrawAnimation( prect, hDCDest, hDCSrc, uAnimateType[rand()%13], nStep, nTimeDelay );
			}	return;
	}

	::BitBlt( hDCDest, nLeft, nTop, nWidth, nHeight, hDCSrc, 0, 0, SRCCOPY );
}

CCompatibleDC::CCompatibleDC(CDC* pDC, CBitmap* pBitmap)
{
	CreateCompatibleDC(pDC);
	m_pBmp = SelectObject(pBitmap);
}

CCompatibleDC::~CCompatibleDC()
{
	SelectObject(m_pBmp);
	DeleteDC();
}

/////////////////////////////////////////
/////////内存设备映射动画///////////////
////////////////////////////////////////
CAnimationMemDC::CAnimationMemDC( CDC *pDC, CRect *prect ) : CMemDC( pDC, prect )
{
}


CAnimationMemDC::~CAnimationMemDC()
{
}

void CAnimationMemDC::Animation( int nType, int nStep, int nTimeDelay )
{
	DrawAnimation( &m_rect, m_pDC->GetSafeHdc(), this->GetSafeHdc(), nType, nStep, nTimeDelay );
}
